#ifndef _X_SLOT_SIGNAL_H
#define _X_SLOT_SIGNAL_H
 
#include <vector>
#include <memory>
#include <functional>
 
#define emit
#define slots
#define signals public
#define connect(sender, signal, slot) ((sender)->signal.bind(slot))
 
template<typename... Args>
class Slot
{
public:
    using OnFunc = std::function<void(Args&&...)>;
 
    Slot(const OnFunc& func)
        : m_func(func)
    {
        // Do nothing
    }
 
    void exec(Args&&... args)
    {
        m_func(std::forward<Args>(args)...);
    }
 
private:
    OnFunc m_func = nullptr;
};
 
template<typename... Args>
class Signal
{
public:
    using SlotPtr = std::shared_ptr<Slot<Args&&...>>; 
    using OnFunc = std::function<void(Args&&...)>;
 
    void bind(const OnFunc& func)
    {
        m_slotVec.push_back(SlotPtr(new Slot<Args&&...>(func)));
    }
 
    void operator()(Args&&... args)
    {
        for (auto& iter : m_slotVec)
        {
            iter->exec(std::forward<Args>(args)...);
        }
    }
 
private:
    std::vector<SlotPtr> m_slotVec;
};
 
#endif
